package org.kotboot.filter;/**
 * Created by jisong.sun on 2017/9/15.
 */

import org.kotboot.kit.K;
import org.apache.catalina.connector.CoyoteOutputStream;
import org.apache.catalina.connector.OutputBuffer;
import org.apache.tomcat.util.buf.ByteChunk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.Charset;

/**
 * 访问记录
 * jisong.sun 2017/9/15 17:05
 */
public class AccessFilter extends OncePerRequestFilter {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(request, response);
        long endTime = System.currentTimeMillis();
        String retStr = getRetString(response);
        StringBuilder sb = new StringBuilder();
        sb.append("\n")
                .append("url     : ").append(request.getRequestURI()).append("\n")
                .append("param   : ").append(K.http.castMap(request)).append("\n")
                .append("response: ").append(retStr).append("\n")
                .append("costtime: ").append(endTime - startTime).append("ms");
        log.info(sb.toString());
    }

    public String getRetString(HttpServletResponse response) {
        try {
            // 截取响应流
            CoyoteOutputStream outputStream = (CoyoteOutputStream) response.getOutputStream();
            Class<CoyoteOutputStream> outputStreamClass = CoyoteOutputStream.class;
            Field obFiled = outputStreamClass.getDeclaredField("ob");// 取出流对象中的OutputBuffer对象，该对象记录响应到客户端的内容
            obFiled.setAccessible(true);// 设置访问ob属性的权限

            OutputBuffer outputBuffer = (OutputBuffer) obFiled.get(outputStream);// 取出ob
            Class<OutputBuffer> outputBufferClass = OutputBuffer.class;
            Field outputChunkField = outputBufferClass.getDeclaredField("outputChunk");// 取到OutputBuffer中的输出流
            outputChunkField.setAccessible(true);

            ByteChunk byteChunk = (ByteChunk) outputChunkField.get(outputBuffer);
            Charset charset = Charset.forName("UTF-8");
            byteChunk.setCharset(charset);
            return byteChunk.toString();
        } catch (Exception e) {
            return e.getMessage();
        }
    }
}
